﻿namespace Rally_MvvmC.Library
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Data.Entity;
    using System.Data.Entity.Core.Objects;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    using System.Threading.Tasks;

    public class DataCollectionBase
    {
    }

    public class DataCollectionBase<DataStoreType, ViewModelClass, EntityClass> : DataCollectionBase, ICollection<ViewModelClass>
        where DataStoreType : IDataStore
        where ViewModelClass : ViewModelBase<DataStoreType, EntityClass>
        where EntityClass : class
    {
        private DbSet<EntityClass> entitiesCollection;
        private IEnumerable<EntityClass> entities;
        private DataStoreType dataStore;
        
        public DataCollectionBase(DataStoreType dataStore, DbContext dataContext, DbSet<EntityClass> entitiesCollection, IEnumerable<EntityClass> entities)
        : this(dataContext, entitiesCollection, entities)
        {
            this.dataStore = dataStore;
        }

        public DataCollectionBase(DbContext dataContext, DbSet<EntityClass> entitiesCollection, IEnumerable<EntityClass> entities)
        {
            this.DbContext = dataContext;
            this.EntitiesDbSet = entitiesCollection;
            this.entities = entities;
            this.entitiesCollection = entitiesCollection;
            this.ViewModelsCollection = new Collection<ViewModelClass>();
        }

        public IEnumerable<EntityClass> Entities
        {
            get
            {
                if (this.entities == null)
                {
                    if (this.entities is DbSet<EntityClass>)
                    {
                        return this.EntitiesDbSet;
                    }
                    else
                    {
                        this.entities = new Collection<EntityClass>();

                        if (this.entities != null)
                        {
                            foreach (var entity in this.entities)
                            {
                                (this.entities as Collection<EntityClass>).Add(entity);
                            }
                        }
                    }
                }

                return this.entities;
            }
        }

        public ObjectContext EntitiesObjectContext
        {
            get
            {
                return ((IObjectContextAdapter)DbContext).ObjectContext;
            }
        }
        public Func<EntityClass, bool> predicate;
        public int Count
        {
            get
            {
                if (this.Entities is ICollection<EntityClass>)
                {
                    return ((ICollection<EntityClass>)this.Entities).Count;
                }
                else if (this.Entities is DbSet<EntityClass>)
                {
                    if (this.predicate != null)
                    {
                        return ((DbSet<EntityClass>)this.Entities).Count(predicate);
                    }
                    else
                    {
                        return ((DbSet<EntityClass>)this.Entities).Count();
                    }
                }
                return 0;
            }
        }
        
        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        protected DbContext DbContext { get; private set; }

        protected DbSet<EntityClass> EntitiesDbSet { get; private set; }
        
        protected ICollection<ViewModelClass> ViewModelsCollection { get; private set; }

        public DbContext GetEntitiesDbContext()
        {
            return this.DbContext;
        }

        public EntityClass GetEntity(int id)
        {
            var viewModel = this.FirstOrDefault(x => x.Id.Equals(id));
            if (viewModel == null)
            {
                return null;
            }
            else
            {
                return viewModel.Entity;
            }
        }

        public DbSet<EntityClass> GetEntitiesDbSet()
        {
            return this.EntitiesDbSet;
        }

        public ViewModelClass Find(object[] keyValues)
        {
            var model = this.EntitiesDbSet.Find(keyValues);
            return null;
        }

        public virtual System.Collections.Generic.IEnumerator<ViewModelClass> GetEnumerator(Func<EntityClass, bool> predicate)
        {
            if (this.Entities == null)
            {
                return new Collection<ViewModelClass>().GetEnumerator();
            }

            var viewModelsCollection = new HashSet<ViewModelClass>();
            IEnumerable<EntityClass> collection = null;
            if (predicate != null)
            {
                collection = this.Entities.Where(predicate).ToList();
            }
            else
            {
                collection = this.Entities.ToList();
            }

            int count = 0;
            int total = collection.Count();
            int max = 0;
            if (total > 1000)
            {
                max = 100;
            }

            var dbContext = this.GetEntitiesDbContext();
            var entitySet = this.GetEntitiesDbSet();
            foreach (var entity in collection)
            {
                var vmc = (ViewModelClass)Activator.CreateInstance(typeof(ViewModelClass), dbContext, entitySet, entity);
                
                viewModelsCollection.Add(vmc);
                count++;
                if (count > max && max > 0)
                {
                    break;
                }
            }

            return viewModelsCollection.GetEnumerator();
        }

        public virtual System.Collections.Generic.IEnumerator<ViewModelClass> GetEnumerator()
        {
            return this.GetEnumerator(null);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public void Add(ViewModelClass item)
        {
            if (this.Entities is List<EntityClass>)
            {
                (this.Entities as List<EntityClass>).Add(item.Entity);
            }
        }

        public bool Remove(ViewModelClass item)
        {
            return true;
        }

        public void Clear()
        { 
        }

        public bool Contains(ViewModelClass item)
        {
            return true;
        }

        public void CopyTo(ViewModelClass[] array, int arrayIndex)
        { 
        }
    }
}
